package com.xbongbong.paas.script.distributor.impl;

import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.help.menu.InitDistributorMenuHelp;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.script.distributor.DistributorFee;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.ValueAddedTypeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.CouponTempleteEntity;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.MarketingBaseEnum;
import com.xbongbong.saas.enums.dictionary.MarketingStatusEnum;
import com.xbongbong.saas.model.CouponTempleteModel;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.FeeLogEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.FeeLogModel;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author xinpeng.jiang
 * @version V1.0
 * @date 2021/7/22 14:26
 * @since V1.0
 */
@Service("DistributorFee")
public class DistributorFeeImpl implements DistributorFee {

    private static final Logger LOG = LoggerFactory.getLogger(DistributorFeeImpl.class);

    @Resource
    private InitDistributorMenuHelp initDistributorMenuHelp;
    @Resource
    private FeeLogModel feeLogModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private CouponTempleteModel couponTempleteModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private CompanyConfigModel companyConfigModel;

    @Override
    @Async(value = "closeDistributorThreadPool")
    public void distributorFeeClose(Long start, Long now) {
        // 套餐最远结束时间map
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", 0);
        param.put("feeType", ValueAddedTypeEnum.DISTRIBUTOR.getType());
        param.put("columns", " corpid, end_time ");
        List<FeeLogEntity> companyEntityList = feeLogModel.findEntitys(param);
        Map<String, Long> endTimeMap = new HashMap<>(companyEntityList.size());
        companyEntityList.forEach(item -> {
            String corpid = item.getCorpid();
            Long endTime = item.getEndTime();
            if (Objects.nonNull(corpid) && Objects.nonNull(endTime)) {
                if (!endTimeMap.containsKey(corpid) || endTimeMap.get(corpid) < endTime) {
                    endTimeMap.put(corpid, endTime);
                }
            }
        });
        if (endTimeMap.isEmpty()) {
            LOG.warn("【经销商套餐到期脚本】success");
            return;
        }
        // 获取开启中的经销商应用
        param.remove("type");
        param.put("enable", 1);
        param.put("alias", XbbRefTypeEnum.DISTRIBUTOR.getCode());
        param.put("corpidIn", endTimeMap.keySet());
        param.put("columns", " corpid ");
        List<PaasAppEntity> paasAppEntities = paasAppModel.findEntitys(param);
        if (paasAppEntities.isEmpty()) {
            LOG.warn("【经销商套餐到期脚本】success");
            return;
        }
        Set<String> corpidSet = new HashSet<>(paasAppEntities.size());
        paasAppEntities.forEach(item -> corpidSet.add(item.getCorpid()));
        endTimeMap.forEach((key, value) -> {
            // 套餐时间小于当前时间并且经销商是开启的需要关闭
            if (value < now && corpidSet.contains(key)) {
                try {
                    initDistributorMenuHelp.enableDistributor(0, key, true);
                } catch (XbbException e) {
                    // 这里是关闭经销商，不会走到这段逻辑，保险起见打个日志
                    LOG.error("经销商套餐到期脚本关闭出错：", e);
                }
            }
        });
        LOG.warn("【经销商套餐到期脚本】consume:{}s", (DateTimeUtil.getInt() - start));
        LOG.warn("【经销商套餐到期脚本】success");
    }

    @Override
    @Async(value = "closeDistributorThreadPool")
    public void activityExpired(Long start, Long endTime) throws XbbException {
        List<String> corpidList = couponTempleteModel.findCorpid();
        if (CollectionUtils.isEmpty(corpidList)) {
            return;
        }
        for (String corpid : corpidList) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("del", 0);
            param.put("status", MarketingStatusEnum.ONLINE.getCode());
            param.put("endTime", endTime);
            List<CouponTempleteEntity> entities = couponTempleteModel.findEntities(param);
            if (CollectionUtils.isEmpty(entities)) {
                continue;
            }
            for (CouponTempleteEntity entity : entities) {
                //到期处理自动下架
                String key = corpid + StringConstant.UNDER_LINE + entity.getId();
                String value = Objects.isNull(paasRedisHelper.getValue(RedisPrefixConstant.COUPON_NUM_KEY, key)) ? "0" : paasRedisHelper.getValue(RedisPrefixConstant.COUPON_NUM_KEY, key);
                entity.setGetNum(entity.getCouponNum() - Integer.parseInt(value));
                paasRedisHelper.removeValue(RedisPrefixConstant.COUPON_NUM_KEY, key);
                entity.setStatus(MarketingStatusEnum.OFFLINE.getCode());
                entity.getData().put(MarketingBaseEnum.STATUS.getAttr(), MarketingStatusEnum.OFFLINE.getCode());
            }
            couponTempleteModel.updateStatus(entities, corpid);
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("success");
    }

    @Override
    @Async(value = "closeDistributorThreadPool")
    public void distributorCompanyConfigClose(Long start, Long now) {
        // 分页
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.COLUMNS, ParameterConstant.CORPID);
        params.put("feeTypeIn", Arrays.asList(PackageTypeEnum.FREE.getType(), PackageTypeEnum.STANDARD.getType()));
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("status", BasicConstant.ONE);
        params.put("feeEndTimeGte", DateTimeUtil.getInt());
        Integer companyCount = companyModel.getEntitysCount(params);
        LOG.warn("【经销商标准版关闭配置脚本】共{}家公司", companyCount);
        // 查询出所有标准版和免费版公司
        for (int pageNum = 0, pageSize = 1000; pageNum * pageSize < companyCount; pageNum++) {
            int startPage = pageNum * pageSize;
            params.put(ParameterConstant.START, startPage);
            params.put(ParameterConstant.PAGE_NUM, pageSize);
            List<CompanyEntity> companyList = companyModel.findEntitys(params);
            if (CollectionUtils.isEmpty(companyList)) {
                break;
            }
            List<String> companyIds = companyList.stream().map(CompanyEntity::getCorpid).collect(Collectors.toList());
            // 查询价格管理、电子面单、物流跟踪这三个配置并且开启了的
            Map<String, Object> configParams = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            configParams.put(ParameterConstant.COLUMNS, ParameterConstant.ID);
            configParams.put("configAliasIn", Arrays.asList(CompanyConfigEnum.PRICE_MANAGE.getAlias(), CompanyConfigEnum.ELECTRONIC_FACE_SHEET.getAlias(), CompanyConfigEnum.LOGISTICS_TRACKING.getAlias()));
            configParams.put("configValue", BasicConstant.ONE.toString());
            configParams.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            for (int j = 0; j < companyIds.size(); j++) {
                String companyId = companyIds.get(j);
                LOG.warn("【经销商标准版关闭配置脚本】{}/{},当前corpid:{}", startPage + j + 1, companyCount, companyId);
                configParams.put(ParameterConstant.CORPID, companyId);
                List<CompanyConfigEntity> configList = companyConfigModel.findEntityList(configParams);
                // 关闭
                if (CollectionUtils.isEmpty(configList)) {
                    continue;
                }
                configList.forEach(i -> {
                    i.setConfigValue(BasicConstant.ZERO.toString());
                    i.setUpdateTime(DateTimeUtil.getInt());
                });
                companyConfigModel.updateBatch(configList, companyId);
            }
        }
        LOG.warn("【经销商标准版关闭配置脚本】consume:{}s", (DateTimeUtil.getInt() - start));
        LOG.warn("【经销商标准版关闭配置脚本】success");
    }
}
